package com.kun.io;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author FangKun
 * @create 2024-02-03-10:24
 * 每个线程对应一个 selector，每个客户端只绑定到其中一个 selector
 */
public class SelectorThread implements Runnable{

    Selector selector = null;

    LinkedBlockingQueue<Channel> lbq = new LinkedBlockingQueue();

    SelectorThreadGroup stg;

    SelectorThread(SelectorThreadGroup stg){
        try {
            this.stg = stg;
            selector = Selector.open();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {

        while (true){

            try {

                System.out.println(Thread.currentThread().getName() + "before select");
                int nums = selector.select();
                System.out.println(Thread.currentThread().getName() + "after select");

                if (nums > 0){
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();

                    while (iterator.hasNext()){
                        SelectionKey key = iterator.next();
                        iterator.remove();

                        if (key.isAcceptable()){
                            acceptHandler(key);
                        }else if (key.isReadable()){
                            readHandler(key);
                        }else if (key.isWritable()){
                            writeHandler(key);
                        }
                    }
                }

                if(!lbq.isEmpty()){
                    Channel c = lbq.take();

                    if (c instanceof ServerSocketChannel){

                        ServerSocketChannel server = (ServerSocketChannel) c;
                        server.register(selector,SelectionKey.OP_ACCEPT);
                        System.out.println(Thread.currentThread().getName() + "register listen");

                    } else if (c instanceof SocketChannel) {

                        SocketChannel client = (SocketChannel) c;
                        ByteBuffer buffer = ByteBuffer.allocate(4096);
                        client.register(selector,SelectionKey.OP_READ,buffer);

                    }
                }

            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    private void writeHandler(SelectionKey key) {

    }

    private void readHandler(SelectionKey key) {

        ByteBuffer buffer = (ByteBuffer)key.attachment();
        SocketChannel client = (SocketChannel)key.channel();
        buffer.clear();

        while (true){
            try {
                int num = client.read(buffer);
                if (num > 0){
                    buffer.flip();
                    while (buffer.hasRemaining()){
                        client.write(buffer);
                    }
                    buffer.clear();
                }else if (num == 0){
                    break;
                }else if (num < 0){
                    System.out.println("连接断开了");
                    key.cancel();
                    break;
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    private void acceptHandler(SelectionKey key) {
        ServerSocketChannel server = (ServerSocketChannel)key.channel();
        try {
            SocketChannel client = server.accept();
            client.configureBlocking(false);

            //选择selector注册
            stg.nextSelector(client);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}













